#include "udir.h"
#include "str.h"
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <errno.h>
#include <limits.h>

namespace log4x
{
int
udir::access(const string& pathname, int mode)
{
    int m = F_OK;
    if (0x0 == mode || 0x1 == mode)
    {
        m = F_OK;
    }

    if (mode & 0x2)
    {
        m |= W_OK;
    }

    if (mode & 0x4)
    {
        m |= R_OK;
    }

    if (mode & 0x8)
    {
        m |= X_OK;
    }

    if (::access(pathname.c_str(), m) < 0)
    {
        return -1;
    }
    return 0;
}

int udir::copy(const string& src, const string& dest)
{
    char cmd[2*1024] = {0};
    snprintf_s(cmd, sizeof(cmd), "cp -fr %s %s", src.c_str(), dest.c_str());
    system(cmd);

    return 0;
}

void
udir::copy_dir(const string& src, const string& dst)
{
    this->copy(src, dst);
}

void
udir::remove(const string& file)
{
#if 0
    ::remove(file.c_str());
#else
    char cmd[2*1024] = {0};
    snprintf_s(cmd, sizeof(cmd), "rm -fr %s", file.c_str());
    system(cmd);
#endif
}

bool
udir::is_dir(const string& path)
{
    struct stat statbuf;
    if (lstat(path.c_str(), &statbuf) < 0)
    {
        return false;
    }

    return S_ISDIR(statbuf.st_mode);
}

int
udir::mk_dir(const string& path)
{
    string tmp = path;
    if (0 == tmp.length())
    {
        return -1;
    }

    for (std::string::iterator iter = tmp.begin(); iter != tmp.end(); ++iter)
    {
        if (*iter == '\\')
        {
            *iter = '/';
        }
    }
    if (tmp.at(tmp.length() - 1) != '/')
    {
        tmp.append("/");
    }

    std::string::size_type pos = tmp.find('/');
    while (pos != std::string::npos)
    {
        std::string cur = tmp.substr(0, pos - 0);
        if (cur.length() > 0 && !is_dir(cur))
        {
            bool result = false;
            result = (::mkdir(cur.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
            if (!result)
            {
                if (EEXIST != errno)
                {
                    return -1;
                }
            }
        }

        pos = tmp.find('/', pos + 1);
    }

    return 0;
}

int
udir::ls_dir(const string& path, vector<string>& files)
{
    struct dirent *file = NULL;
    DIR *dir = opendir(path.c_str());
    if (!dir)
    {
        return -1;
    }

    while ((file = readdir(dir)) != NULL)
    {
        files.push_back(file->d_name);
    }

    closedir(dir);
    return 0;
}

string
udir::home(const string& name)
{
    struct passwd *user = NULL;
    if ("" != name)
    {
        user = getpwnam(name.c_str());
    }
    else
    {
        user = getpwuid(getuid());
    }

    if (!user)
    {
        return "";
    }

    return user->pw_dir;
}

string
udir::absolute_path(const string& relative_path)
{
    char absolute[PATH_MAX] = { 0 };

    if (!realpath(relative_path.c_str(), absolute))
    {
        return "";
    }

    return absolute;

}

int
udir::stat(const string& path, struct stat& sb)
{

    if (lstat(path.c_str(), &sb) < 0)
    {
        return -1;
    }

    return 0;
}

int
udir::chmod(const string& path, uint32_t mode)
{
    if (::chmod(path.c_str(), (mode_t)mode) < 0)
    {
        return -1;
    }

    return 0;
}
}
